package com.example.aop;

import com.example.pojo.OperateLog;
import com.example.mapper.OperateLogMapper;
import com.example.utils.CurrentHolder;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.Arrays;

@Slf4j
@Component
@Aspect
public class OperationLogAspect {

    @Autowired
    private OperateLogMapper operateLogMapper;

    // 定义切点，匹配com.example.controller包下所有标记了@Log注解的方法
    @Pointcut("@annotation(com.example.anno.Log)")
    public void logPointCut() {
    }

    // 环绕通知
    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object result = null;
        try {
            // 执行目标方法
            result = joinPoint.proceed();
            return result;
        } finally {
            // 记录操作日志
            handleLog(joinPoint, result, System.currentTimeMillis() - startTime);
        }
    }

    /**
     * 处理并保存操作日志
     *
     * @param joinPoint 连接点
     * @param result    方法返回值
     * @param costTime  方法执行耗时
     */
    private void handleLog(ProceedingJoinPoint joinPoint, Object result, long costTime) {
        try {
            // 获取目标类名
            String className = joinPoint.getTarget().getClass().getName();
            // 获取方法名
            String methodName = joinPoint.getSignature().getName();
            // 获取方法参数
            String methodParams = Arrays.toString(joinPoint.getArgs());

            // 创建操作日志对象
            OperateLog operateLog = new OperateLog();
            // 操作人ID，这里假设从SecurityContext或ThreadLocal中获取，示例中写死为1
            // 实际项目中应根据登录用户动态获取
            operateLog.setOperateEmpId(CurrentHolder.getCurrentId());
            operateLog.setOperateTime(LocalDateTime.now());
            operateLog.setClassName(className);
            operateLog.setMethodName(methodName);
            operateLog.setMethodParams(methodParams);
            operateLog.setReturnValue(result != null ? result.toString() : "");
            operateLog.setCostTime(costTime);

            // 保存到数据库
            log.info("记录日志操作: {}", operateLog);
            operateLogMapper.insert(operateLog);
        } catch (Exception e) {
            log.error("记录操作日志异常", e);
        }
    }
}
